﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
using ShredTheLog.Api;
using System.Diagnostics.Contracts;
using System.Globalization;

namespace ShredTheLog.Model
{
    [XmlRoot("NU")]
    public class UserInfo : IUserInfo
    {
        [XmlAttribute("UID")]
        public int Uid { get; set; }

        public override string ToString()
        {
            return Uid.ToString(CultureInfo.InvariantCulture);
        }
    }

    [XmlRoot("Member")]
    public class BasicUserInfo : UserInfo, IBasicUserInfo
    {
        [XmlAttribute("FN")]
        public string FirstName { get; set; }

        [XmlAttribute("LN")]
        public string LastName { get; set; }

        [XmlAttribute("LID")]
        public int CountryId { get; set; }

        [XmlIgnore]
        public Country Country
        {
            get { return (Country)CountryId; }
            set { CountryId = (int)value; }
        }

        [XmlAttribute("A")]
        public virtual int Age { get; set; }

        [XmlAttribute("G")]
        public int GenderId { get; set; }

        [XmlIgnore]
        public Gender Gender
        {
            get { return (Gender)GenderId; }
            set { GenderId = (int)value; }
        }

        public string Name
        {
            get
            {
                return
                    String.IsNullOrEmpty(LastName) ?
                    (String.IsNullOrEmpty(FirstName) ? String.Empty : FirstName) :
                    (String.IsNullOrEmpty(FirstName) ? LastName : String.Format(CultureInfo.CurrentCulture, "{0} {1}", FirstName, LastName));
            }
        }

        public override string ToString()
        {
            if (String.IsNullOrEmpty(Name))
                return base.ToString();
            else
                return Name;
        }
    }

    public class ShortUserInfo : BasicUserInfo, IShortUserInfo
    {
        [XmlAttribute("KLs")]
        public string KnownLanguageIdentifiers { get; set; }

        [XmlAttribute("PLs")]
        public string PracticingLanguageIdentifiers { get; set; }

        private static readonly Language[] EmptyLanguageList = new Language[0];

        [XmlIgnore]
        public IEnumerable<Language> KnownLanguages
        {
            get
            {
                Contract.Ensures(Contract.Result<IEnumerable<Language>>() != null);

                if (!String.IsNullOrEmpty(KnownLanguageIdentifiers))
                    return from ls in KnownLanguageIdentifiers.Split('|') select (Language)Int32.Parse(ls, CultureInfo.InvariantCulture);
                else
                    return EmptyLanguageList;
            }
            set
            {
                KnownLanguageIdentifiers =
                    value != null ?
                    String.Join("|", value.Select(i => ((int)i).ToString(CultureInfo.InvariantCulture))) :
                    String.Empty;
            }
        }

        [XmlIgnore]
        public IEnumerable<Language> PracticingLanguages
        {
            get
            {
                Contract.Ensures(Contract.Result<IEnumerable<Language>>() != null);

                if (!String.IsNullOrEmpty(PracticingLanguageIdentifiers))
                    return from ls in PracticingLanguageIdentifiers.Split('|') select (Language)Int32.Parse(ls, CultureInfo.InvariantCulture);
                else
                    return EmptyLanguageList;
            }
            set
            {
                PracticingLanguageIdentifiers =
                    value != null ?
                    String.Join("|", value.Select(i => ((int)i).ToString(CultureInfo.InvariantCulture))) :
                    String.Empty;
            }
        }
    }

    public sealed class Last15UserInfo : ShortUserInfo, ILast15UserInfo
    {
        [XmlAttribute("BD")]
        public DateTime BirthDate { get; set; }

        [XmlAttribute("A")]
        public override int Age
        {
            get
            {
                DateTime now = DateTime.Now;
                return now.Year - BirthDate.Year - ((now.Month < BirthDate.Month) || (now.Month == BirthDate.Month && now.Day < BirthDate.Day) ? 1 : 0);
            }
            set
            {
                // Do nothing. Server tries to set 0, which is not what we really need here...
            }
        }
    }

    public sealed class Contact : ShortUserInfo, IContact
    {
        [XmlAttribute("RID")]
        public int RID { get; set; }

        /// <summary>
        /// Дата и время добавления контакта в UTC
        /// </summary>
        [XmlAttribute("CD")]
        public DateTime CreationDate { get; set; }

        /// <summary>
        /// ???
        /// </summary>
        /// <remarks>
        /// Всегда 1
        /// </remarks>
        [XmlAttribute("S")]
        public int S { get; set; }

        /// <summary>
        /// Статус пользователя
        /// </summary>
        /// <remarks>
        /// Возможные значения: Accepted, Deleted
        /// </remarks>
        [XmlAttribute("US")]
        public string US { get; set; }
    }

    [XmlRoot("P")]
    public class FullUserInfo : ShortUserInfo, IFullUserInfo
    {
        [XmlAttribute("US")]
        public string US { get; set; }

        [XmlAttribute("L")]
        public string Location { get; set; }

        [XmlAttribute("D")]
        public string Description { get; set; }

        [XmlAttribute("XCM")]
        public int DoesNotExchangeEmails { get; set; }
        [XmlIgnore]
        public bool ExchangesEmails { get { return DoesNotExchangeEmails == 0; } }

        [XmlAttribute("XCC")]
        public int DoesNotChatOnline { get; set; }
        [XmlIgnore]
        public bool ChatsOnline { get { return DoesNotChatOnline == 0; } }

        [XmlAttribute("RD")]
        public DateTime RegistrationDate { get; set; }
    }

    [XmlRoot("U")]
    public sealed class SessionCredentials : FullUserInfo, ISessionCredentials
    {
        [XmlAttribute("SSID")]
        public string Ssid { get; set; }

        [XmlAttribute("IS")]
        public string IS { get; set; }

        [XmlAttribute("UN")]
        public string UserName { get; set; }

        [XmlAttribute("PW")]
        public string Password { get; set; }

        [XmlAttribute("E")]
        public string Email { get; set; }

        [XmlAttribute("NM")]
        public int NM { get; set; }

        [XmlAttribute("RWorldIsOn")]
        public bool RWorldIsOn { get; set; }

        [XmlAttribute("BD")]
        public DateTime BirthDate { get; set; }
    }
}
